package vben.core.module.sys.org.role;

import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import vben.core.common.mvc.api.PageData;
import vben.core.common.mvc.dao.JdbcDao;
import vben.core.common.mvc.dao.Sqler;
import vben.core.common.mvc.pojo.ZidOrnum;
import vben.core.common.mvc.pojo.TreeMovePo;
import vben.core.common.mvc.pojo.ZidName;
import vben.core.common.utils.lang.IdUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional(rollbackFor = Exception.class)
public class SysOrgRoleNodeService {

    @Transactional(readOnly = true)
    public SysOrgRoleNode findById(String id) {
        return repo.findById(id).get();
    }

    public SysOrgRoleNode insert(SysOrgRoleNode main) {
        if (main.getId() == null || "".equals(main.getId())) {
            main.setId(IdUtils.getUID());
        }
        if (main.getParent() == null || StrUtil.isBlank(main.getParent().getId())) {
            main.setTier("x" + main.getId() + "x");
        } else {
            String tier = jdbcDao.findOneString("select tier from sys_org_role_node where id=?", main.getParent().getId());
            main.setTier(tier + main.getId() + "x");
        }
        return repo.save(main);
    }


    public SysOrgRoleNode update(SysOrgRoleNode main) throws Exception {
        main.setUptim(new Date());
        if (main.getParent() == null || StrUtil.isBlank(main.getParent().getId())) {
            main.setTier("x" + main.getId() + "x");
        } else {
            String tier = jdbcDao.findOneString("select tier from sys_org_role_node where id=?", main.getParent().getId());
            main.setTier(tier + main.getId() + "x");
            String[] arr = tier.split("x");
            for (String str : arr) {
                if (main.getId().equals(str)) {
                    throw new Exception("父层级不能为自己或者自己的子层级");
                }
            }
        }
        SysOrgRoleNode backTier = repo.save(main);
        String oldTier = jdbcDao.findOneString("select tier from sys_org_role_node where id=?", main.getId());
        if(!oldTier.equals(main.getTier())){
            dealTier(oldTier, main.getTier(), main.getId());
        }
        return backTier;
    }

    public int delete(String[] ids) {
        for (String str : ids) {
            repo.deleteById(str);
        }
        return ids.length;
    }

    private void dealTier(String oldTier, String newTier, String id) {
        String sql = "select id,tier as name from sys_org_role_node where tier like ? and id<>?";
        List<ZidName> list = jdbcDao.findIdNameList(sql, oldTier + "%", id);
        String updateSql = "update sys_org_role_node set tier=? where id=?";
        List<Object[]> updateList = new ArrayList<Object[]>();
        batchReady(oldTier, newTier, list, updateList);
        jdbcDao.batch(updateSql, updateList);
    }


    private void batchReady(String oldTier, String newTier, List<ZidName> list, List<Object[]> updateList) {
        for (ZidName ztwo : list) {
            Object[] arr = new Object[2];
            arr[1] = ztwo.getId();
            arr[0] = ztwo.getName().replace(oldTier, newTier);
            updateList.add(arr);
        }
    }

    public List<SysOrgRoleNode> findAll(Sqler sqler) {
        List<SysOrgRoleNode> list = jdbcDao.getTp().query(sqler.getSql(), sqler.getParams(), new BeanPropertyRowMapper<>(SysOrgRoleNode.class));
        return list;
    }

    public PageData findPageData(Sqler sqler) {
        return jdbcDao.findPageData(sqler);
    }

    public List<SysOrgRoleNode> findTree(Sqler sqler) {
        List<SysOrgRoleNode> list = jdbcDao.getTp().query(sqler.getSql(), sqler.getParams(), new BeanPropertyRowMapper<>(SysOrgRoleNode.class));
        return buildByRecursive(list);
    }

    //使用递归方法建树
    private List<SysOrgRoleNode> buildByRecursive(List<SysOrgRoleNode> nodes) {
        List<SysOrgRoleNode> list = new ArrayList<>();
        for (SysOrgRoleNode node : nodes) {
            if (node.getPid() == null) {
                list.add(findChildrenByTier(node, nodes));
            } else {
                boolean flag = false;
                for (SysOrgRoleNode node2 : nodes) {
                    if (node.getPid().equals(node2.getId())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    list.add(findChildrenByTier(node, nodes));
                }
            }
        }
        return list;
    }

    //递归查找子节点
    private SysOrgRoleNode findChildrenByTier(SysOrgRoleNode node, List<SysOrgRoleNode> nodes) {
        for (SysOrgRoleNode item : nodes) {
            if (node.getId().equals(item.getPid())) {
                if (node.getChildren() == null) {
                    node.setChildren(new ArrayList<>());
                }
                node.getChildren().add(findChildrenByTier(item, nodes));
            }
        }
        return node;
    }


//    public List<SysOrgRoleTree> findWithoutItself(Sqler sqler, String id) {
//        List<SysOrgRoleTree> list = jdbcDao.getTp().query(sqler.getSql(), sqler.getParams(), new BeanPropertyRowMapper<>(SysOrgRoleTree.class));
//        return buildByRecursiveWithoutItself(list, id);
//    }

    //使用递归方法建树不包含自己
//    private List<SysOrgRoleTree> buildByRecursiveWithoutItself(List<SysOrgRoleTree> nodes, String id) {
//        List<SysOrgRoleTree> list = new ArrayList<>();
//        for (SysOrgRoleTree node : nodes) {
//            if (node.getPid() == null && !node.getId().equals(id)) {
//                list.add(findChildrenByTierWithoutItself(node, nodes, id));
//            } else {
//                boolean flag = false;
//                for (SysOrgRoleTree node2 : nodes) {
//                    if (node.getPid() != null && node.getPid().equals(node2.getId())) {
//                        flag = true;
//                        break;
//                    }
//                }
//                if (!flag && !node.getId().equals(id)) {
//                    list.add(findChildrenByTierWithoutItself(node, nodes, id));
//                }
//            }
//        }
//        return list;
//    }

    //递归查找子节点不包含自己
//    private SysOrgRoleTree findChildrenByTierWithoutItself(SysOrgRoleTree node, List<SysOrgRoleTree> nodes, String id) {
//        for (SysOrgRoleTree item : nodes) {
//            if (node.getId().equals(item.getPid()) && (!item.getId().equals(id))) {
//                if (node.getChildren() == null) {
//                    node.setChildren(new ArrayList<>());
//                }
//                node.getChildren().add(findChildrenByTierWithoutItself(item, nodes, id));
//            }
//        }
//        return node;
//    }

    public Integer getCount(String pid,String treid){
        if(StrUtil.isNotBlank(pid)){
            String countSql="select count(1) from sys_org_role_node where pid=?";
            Integer count = jdbcDao.getTp().queryForObject(countSql, new Object[]{pid}, Integer.class);
            if(count==null){
                count=0;
            }
            return count;
        }else{
            String countSql="select count(1) from sys_org_role_node where pid is null and treid=?";
            Integer count = jdbcDao.getTp().queryForObject(countSql,new Object[]{treid}, Integer.class);
            if(count==null){
                count=0;
            }
            return count;
        }
    }


    public void move(TreeMovePo po) throws Exception {
        SysOrgRoleNode dragDept= repo.findById(po.getDraid()).get();
        if(dragDept.getParent()!=null){
            dragDept.setPid(dragDept.getParent().getId());
        }

        List<ZidOrnum> list2;

        if(StrUtil.isNotBlank(dragDept.getPid())){
            String sql = "select id,ornum from sys_org_role_node where ornum>? and pid=?";
            list2 = jdbcDao.getTp().query(sql,new Object[]{dragDept.getOrnum(),dragDept.getPid()},
                    new BeanPropertyRowMapper<>(ZidOrnum.class));
        }else{
            String sql = "select id,ornum from sys_org_role_node where ornum>? and treid=? and pid is null";
            list2 = jdbcDao.getTp().query(sql,new Object[]{dragDept.getOrnum(),dragDept.getTreid()},
                    new BeanPropertyRowMapper<>(ZidOrnum.class));
        }

        String updateSql = "update sys_org_role_node set ornum=? where id=?";
        List<Object[]> updateList = new ArrayList<>();
        for (ZidOrnum zidOrnum : list2) {
            Object[] arr=new Object[2];
            arr[0]=zidOrnum.getOrnum()-1;
            arr[1]=zidOrnum.getId();
            updateList.add(arr);
        }
        jdbcDao.batch(updateSql, updateList);
        if ("inner".equals(po.getType()))
        {
            dragDept.setPid(po.getDroid());
            dragDept.setParent(new SysOrgRoleNode(dragDept.getPid()));
            Integer count=getCount(po.getDroid(),dragDept.getTreid());
            dragDept.setOrnum(count+1);
        }
        else if ("before".equals(po.getType()))
        {
            SysOrgRoleNode dropDept= repo.findById(po.getDroid()).get();
            if(dropDept.getParent()!=null){
                dropDept.setPid(dropDept.getParent().getId());
                dragDept.setPid(dropDept.getPid());;
                dragDept.setParent(dropDept.getParent());;
            }else{
                dragDept.setPid(null);
                dragDept.setParent(null);
            }
            dragDept.setOrnum(dropDept.getOrnum());

            List<ZidOrnum> list3;
            if(StrUtil.isNotBlank(dropDept.getPid())){
                String sql3 = "select id,ornum from sys_org_role_node where ornum>? and pid=?";
                list3 = jdbcDao.getTp().query(sql3,new Object[]{dropDept.getOrnum(),dropDept.getPid()},
                        new BeanPropertyRowMapper<>(ZidOrnum.class));
            }else{
                String sql3 = "select id,ornum from sys_org_role_node where ornum>? and treid=? and pid is null";
                list3 = jdbcDao.getTp().query(sql3,new Object[]{dropDept.getOrnum(),dropDept.getTreid()},
                        new BeanPropertyRowMapper<>(ZidOrnum.class));
            }

            String updateSql3 = "update sys_org_role_node set ornum=? where id=?";
            List<Object[]> updateList3 = new ArrayList<>();
            for (ZidOrnum zidOrnum : list3) {
                Object[] arr=new Object[2];
                arr[0]=zidOrnum.getOrnum()+1;
                arr[1]=zidOrnum.getId();
                updateList3.add(arr);
            }
            jdbcDao.batch(updateSql3, updateList3);
            dropDept.setOrnum(dropDept.getOrnum()+1);
            String updateSql4 = "update sys_org_role_node set ornum=? where id=?";
            jdbcDao.update(updateSql4, dropDept.getOrnum(), dropDept.getId());
        }
        else if ("after".equals(po.getType()))
        {
            SysOrgRoleNode dropDept= repo.findById(po.getDroid()).get();
            if(dropDept.getParent()!=null){
                dropDept.setPid(dropDept.getParent().getId());
            }
            Integer count = getCount(dropDept.getPid(),dropDept.getTreid());
            if (dragDept.getPid()!=null&&dragDept.getPid().equals(dropDept.getPid()))
            {
                dragDept.setOrnum(count);
            }
            else
            {
                dragDept.setPid(dropDept.getPid());
                if (dragDept.getPid() == null)
                {
                    dragDept.setParent(null);
                }
                else
                {
                    dragDept.setParent(new SysOrgRoleNode(dragDept.getPid()));
                }
                dragDept.setOrnum(count+1);
            }
        }
        update(dragDept);
    }

    @Autowired
    private JdbcDao jdbcDao;

    @Autowired
    private SysOrgRoleNodeRepo repo;


}
